﻿// JScript File - searchClient class
//
// The constructor accepts the ID of a DIV tag where instructions are shown, 
// and the ID of a DIV tag where search results are shown.
// There is only one public method, namely search(keyword).
// The search results are shown in a way similar to what www.live.com had at
// one point where results can be scrolled through.
//
// This client side AJAX class is designed specifically to be used together
// with searchProxy.aspx.
// 
function searchClient(eleInstruction, eleResult, strScope) {
    //
    // member variables
    //
    var m_strScope = strScope;
    var m_iInterval = null;
    var m_iPage = 0;         // offset page count for search results
    var m_iPageMax = 25;     // bounds to ensure no endless requests
    var m_iCount = 10;       // count of search results
    var m_strKey;            // keyword being searched
    var m_xmlhttp = null;
    var m_oInstructions;
    var m_oResult;
    //
    // member methods
    //
    this.search = search;

    //
    // m_xmlhttp creation
    //
    if (typeof window.XMLHttpRequest != "undefined") {
        m_xmlhttp = new window.XMLHttpRequest();
    } else if (window.ActiveXObject) {
        var ver = [ 
            "MSXML2.XMLHttp.5.0",
            "MSXML2.XMLHttp.4.0",
            "MSXML2.XMLHttp.3.0",
            "MSXML2.XMLHttp",
            "Microsoft.XMLHttp"];
        for (var i = 0; i < ver.length; i++) {
            try { m_xmlhttp = new window.ActiveXObject(ver[i]); break; }
            catch (e) {}
        }
    }
    if (m_xmlhttp == null) {
        m_oResult.innerHTML  = "<p><h4>Failure to create m_xmlhttp</h4></p><p>Please refresh the page.</p>";
    }
    
    //
    // user interaction
    //
    function search(strKey) {
        // initialize references to elements
        m_oInstructions = document.getElementById(eleInstruction);
        m_oResult = document.getElementById(eleResult);    
        
        if (strKey == "") {
            m_oInstructions.innerHTML = "Enter search keywords";
            return false;
        }
        if (m_xmlhttp.readyState>=1 && m_xmlhttp.readyState<=3) {
            return false; // prevents starting a new search if an xmlhttp request is in progress
        }
        m_strKey = strKey;
        m_iPage = 0;

        m_oResult.innerHTML = "";
        m_oInstructions.innerHTML = hesc(m_strKey);

        update();
        return false;
    }
    
    //
    // obtain search results
    //
    function update() {
        if (m_strKey != "" && m_xmlhttp != null && (m_xmlhttp.readyState==0 || m_xmlhttp.readyState==4)) {
            try {
                m_oInstructions.innerHTML += " - Loading results...";
                var s = "http://" + window.location.host + window.location.pathname;
                s = s.split('/');
                s[s.length - 1] = "searchproxy.aspx";
                
                m_xmlhttp.open("GET", 
                    s.join('/') +
                    "?searchKey=" + encodeURIComponent(m_strScope + " " + m_strKey) +
                    "&searchCount=" + m_iCount +
                    "&searchOffset=" + (m_iPage * m_iCount),true);
                m_xmlhttp.onreadystatechange=xmlhttpCallback;
                clearTimer();
                m_xmlhttp.send(null);
            } catch (e) {
                document.getElementById(eleResult).innerHTML =
                    "<p><h4>Xmlhttp error</h4></p>" +
                    "<p>Please repeat the query.</p>" +
                    e;
                clearTimer();
            }
        }
    }
    
    function xmlhttpCallback() {
        try {
            if (m_xmlhttp.readyState==4) {
                if (m_xmlhttp.status ==200) {
                    var s = m_xmlhttp.responseText.split('#');
                    m_oInstructions.innerHTML = hesc(m_strKey) + "\t(" + s[0] + ")";
                    if (s[0] == 0 || s[1] == "") {
                        clearTimer();
                    } else {
                        s.shift();
                        document.getElementById(eleResult).innerHTML += s.join('#');
                        setTimer();
                    }
                } else {
                    document.getElementById(eleResult).innerHTML =
                        "<p><h4>Xmlhttp error</h4></p>" +
                        "<p>Please repeat the query.</p>" +
                        "<p>" + m_xmlhttp.status + "</p>" +
                        "<p>" + m_xmlhttp.statusText + "</p>" +
                        "<p>" + m_xmlhttp.responseText + "</p>";                        
                }
            }
        } catch(e) {
            document.getElementById(eleResult).innerHTML =
                "<p><h4>Xmlhttp error on callback</h4></p>" +
                "<p>Please repeat the query.</p>";
        }
    }

    //
    // timer utilities
    //
    function setTimer() {
        clearTimer();
        m_iInterval = window.setInterval(getMoreResults, 1000);
    }
    function clearTimer() {
        if (m_iInterval != null) {
            window.clearInterval(m_iInterval);
            m_iInterval = null;
        }            
    }
    function getMoreResults() {
        var oReturn = document.getElementById('returnArea');
        if (oReturn.scrollTop > oReturn.scrollHeight - oReturn.offsetHeight * 2) {
            m_iPage ++ ;
            if (m_iPage > m_iPageMax) {
                clearTimer();
            } else {
                update();
            }
        }
    }
    
    // escape functions
    function hesc(p_str) {
        return p_str.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
    }
}

